  int n, m;
	cin >> n >> m;

	vector<vector<char>> s(n, vector<char>(m));
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			cin >> s[i][j];
		}
	}

	if (n < m) {
		vector<vector<char>> t(m, vector<char>(n));
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < m; j++) {
				t[j][i] = s[i][j];
			}
		}
		s = t;
		swap(n, m);
	}

	vector<ll> pw(m + 1);
	pw[0] = 1;
	for (int i = 1; i <= m; i++) {
		pw[i] = pw[i - 1] * 10;
	}

	unordered_map<ll, Z> dp;
	dp[0] = 1;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < m; j++) {
			unordered_map<ll, Z> ndp;
			for (auto &[k, v]: dp) {
				ll ups = k / pw[j] % 10, lhs = -1;
				if (j != 0) {
					lhs = k / pw[j - 1] % 10;
				}
				for (int c = 1; c <= 3; c++) {
					if (c != ups && c != lhs && ((s[i][j] == '?') || (s[i][j] - '0' == c))) {
						ll r = k - ups * pw[j];
						ndp[r + pw[j] * c] += v;
					}
				}
			}
			dp.swap(ndp);
		}
	}

	Z ans(0);
	for (auto &[k, v]: dp) {
		ans += v;
	}
	cout << ans;